package com.javacv.plus.core.processor;

import com.javacv.plus.core.config.ProcessorConfig;
import com.javacv.plus.core.exception.ProcessorException;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
 * 媒体处理器基础抽象类
 * 使用模板方法模式定义处理流程
 * 
 * @param <T> 处理器类型
 * @param <R> 结果类型
 */
@Slf4j
public abstract class MediaProcessor<T extends MediaProcessor<T, R>, R> {

    protected ProcessorConfig config;
    protected List<ProcessorStep<T, R>> steps = new ArrayList<>();
    protected ProcessorChain<T, R> chain;

    protected MediaProcessor(ProcessorConfig config) {
        this.config = config;
        this.chain = new ProcessorChain<>();
    }

    /**
     * 添加处理步骤
     */
    @SuppressWarnings("unchecked")
    public T addStep(ProcessorStep<T, R> step) {
        this.steps.add(step);
        this.chain.addStep(step);
        return (T) this;
    }

    /**
     * 处理模板方法
     */
    public R process() throws ProcessorException {
        try {
            log.info("开始处理，配置: {}", config);
            
            // 前置处理
            beforeProcess();
            
            // 执行处理链
            R result = executeProcess();
            
            // 后置处理
            afterProcess(result);
            
            log.info("处理完成");
            return result;
            
        } catch (Exception e) {
            handleError(e);
            throw new ProcessorException("处理失败", e);
        }
    }

    /**
     * 前置处理钩子方法
     */
    protected void beforeProcess() {
        log.debug("执行前置处理");
    }

    /**
     * 执行具体处理逻辑
     */
    protected abstract R executeProcess() throws Exception;

    /**
     * 后置处理钩子方法
     */
    protected void afterProcess(R result) {
        log.debug("执行后置处理，结果: {}", result);
    }

    /**
     * 错误处理钩子方法
     */
    protected void handleError(Exception e) {
        log.error("处理过程中发生错误", e);
    }

    /**
     * 获取配置
     */
    public ProcessorConfig getConfig() {
        return config;
    }

    /**
     * 更新配置
     */
    @SuppressWarnings("unchecked")
    public T withConfig(ProcessorConfig config) {
        this.config = config;
        return (T) this;
    }
} 